# !/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time        : 2020/11/5 19:29
@Author      : Albert Darren
@Contact     : 2563491540@qq.com
@File        : iteration.py
@Version     : Version 1.0.0
@Description : TODO 迭代法
@Created By  : PyCharm
"""

from decimal import Decimal, getcontext


def iterate_positive_root(x0=1, iteration_depth=5):
    """
    迭代法求一元二次方程正根的近似解x*
    :param x0: 初始近似值,默认为1
    :param iteration_depth: 迭代次数或深度,默认是5次
    :return: 方程的近似解
    """
    x = x0
    for i in range(iteration_depth):
        x = 1 / (1 + x)
    return x0, iteration_depth, x


def iterate_sqrt(radicand: (int, float), initial_value: (int, float), precision: float = -9):
    """
    返回在指定精度和初始近似值下的被开方数的平方根
    :param radicand:被开方数
    :param initial_value:初始近似值x0
    :param precision:迭代计算精度，用幂指数表示精度，默认为-9，即10的﹣9次方或者1e-09
    :return:the square root of radicand
    """
    # 默认高精度浮点运算为28位,包括整数位和小数位,设置准确值的位数
    getcontext().prec = abs(precision) + 2
    sqrt = initial_value
    # 准确值
    accuracy_value = pow(Decimal(radicand), Decimal(0.5))
    # 绝对误差
    absolute_error = 0.5 * pow(10, precision)
    # 计数器，统计迭代次数
    count = 0
    while 1:
        # 迭代误差
        error = abs(accuracy_value - Decimal(sqrt))
        if error < absolute_error:
            return radicand, initial_value, count, accuracy_value, sqrt
        sqrt = 0.5 * (sqrt + radicand / sqrt)
        count += 1


if __name__ == '__main__':
    results = iterate_sqrt(7, 2.5)
    print("""
被开方数a={}
初始近似值x0={}
迭代{}次与准确值x={}达到误差要求
结果x*={}
    """.format(results[0], results[1], results[2], results[3], results[4]))
